package tools;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.io.Serializable;

public class Hand implements Serializable  
{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1408608011851545747L;
	private ArrayList<Card> hand;
	
	public Hand(Card c1, Card c2, Card c3, Card c4)
	{
		hand = new ArrayList<Card>();
		
		hand.add(0,c1);
		hand.add(1,c2);
		hand.add(2,c3);
		hand.add(3,c4);
	}
	
	public Hand(ArrayList<Card> cards)
	{
		hand = cards;
	}
	
	public ArrayList<Card> getCardList()
	{
		return hand;
	}
	/*
	 * wymiana kart
	 * */
	public void swapCards(ArrayList<Card> oldCards, ArrayList<Card> newCards)
	{
		for(int i=0; i<oldCards.size(); i++)
			for(int j=0; j<hand.size(); j++)
				if (hand.get(j).getValue() == oldCards.get(i).getValue() 
				    && hand.get(j).getSuit().equals(oldCards.get(i).getSuit()))
				{
					hand.remove(j);
					hand.add(j, newCards.get(i));
				}
	}
	
	/*
	 * 1. zrobienie tablic kolorow
	 * 2. Sortowanie wartosci w kazdej tablicy rosnaco
	 * 3. Sortowanie tablic wg ilosci zawartosci malejaco (przypadek gdy sa dwie tablice z dwoma kartami, to sortowanie wg najwiekszych wartosci rosnaco)
	 * 4. Porownanie kart zaczynajac od pierwszej tablicy i pierwszego elementu: jesli karta z ta wartoscia jest w innej tabllicy (idac w prawo) to ja pomijamy, 
	 *    w przeciwnym przypadku jest brana do rozkladu
	 * */
	
	public int compareTo(Hand h)
   {
		/*
		 * porownujemy dwa zestawy kart
		 * najpierw wybieramy karty biorace udzial w porownaniu, czyli prawidlowe zestawy
		 * 
		 * */
		ArrayList<Card> thisCards = this.getCards();
		ArrayList<Card> otherCards = h.getCards();
		
		int diffQuantity = thisCards.size() - otherCards.size();
		/*
		 * jesli rozne ilosci waznych kart to wygrywa wieksza ilosc
		 * */
		if (diffQuantity != 0)
			return diffQuantity;
		
		for(int i=0; i<thisCards.size(); i++)
			if (otherCards.get(i).compareTo(thisCards.get(i)) != 0)
					return otherCards.get(i).compareTo(thisCards.get(i));
		/*
		 * jesli wszystkie karty sa tej samej wartosci
		 * */
		return 0;
   }
	 
	public ArrayList<Card> getCards()
	{
		ArrayList<ArrayList<Card>> matrix = new ArrayList<ArrayList<Card>>();
		ArrayList<Card> cards = new ArrayList<Card>();
		
		/*
		 * Utowarzenie 4 kolumn macierzy. Jedna kolumna, to jeden kolor.
		 * */
		matrix.add(0, new ArrayList<Card>());
		matrix.add(1, new ArrayList<Card>());
		matrix.add(2, new ArrayList<Card>());
		matrix.add(3, new ArrayList<Card>());
		
		for(Card c : hand)
			switch(c.getSuit())
			{
         	case ("s"):
         		matrix.get(0).add(c);
         		break;
         	case ("h"):
         		matrix.get(1).add(c);
               break;
         	case ("d"):
         		matrix.get(2).add(c);
               break;
         	case ("c"):
         		matrix.get(3).add(c);
               break;
          }
		/*
		 * Posortowanie kazdej kolumny rosnaca wg wartosci kart
		 * */
		Collections.sort(matrix.get(0));
		Collections.sort(matrix.get(1));
		Collections.sort(matrix.get(2));
		Collections.sort(matrix.get(3));
		
		/*
		 * Posortowanie kolumn macierzy, malejaco wg ilosci kart w kolumnie
		 * */
		Collections.sort(matrix, ColorListComparator);
		
		/*
		 * Pokazanie macierzy kart
		 * */
		/*
		for(ArrayList<Card> w: matrix)
		{
			for(Card e: w)
			{
				System.out.print(e.getRank()+e.getSuit()+",");
			}
			System.out.println("");
		}
		*/

		/* 
		 * Wybor kart do porownania
		 *
		 **/
		boolean choose = true;
		boolean chosen = false;
		/*
		 * dla kazdej kolumny
		 * */
		for(int i=0; i<matrix.size(); i++) // lista kolumn kolorow
		{
			/*
			 * dla kazdej karty w kolumnie
			 * */
			chosen = false; // nie wybralismy jeszcze karty
			for(int j=0; j<matrix.get(i).size(); j++) // dla kazdej karty w kolumnie
			{
				choose = true; // wybieramy dana karte
				Card c = matrix.get(i).get(j); // bierzemy nasza karte z itej kolumny i jta karte
				/*
				 * Sprawdz czy karta o tej samej wartosci jest w nastepnych kolumnach
				 * */
				for(int z=i+1; z<matrix.size(); z++) // z=i+1 to nastepna kolumna
				{
					//System.out.println("check: "+c.getRank()+c.getSuit()+" does contain list "+z);
					if (matrix.get(z).contains(c)) // sprawdzamy czy w nastepnej(ztej) kolumnie jest karta o tej samej wartosci
					{
						//System.out.println("jest: "+c.getRank()+c.getSuit());
						/*
						 * jesli jest karta o danej wartosci w pozostalych kolumnach, to nie bierzemy karty i sprawdzamy nastepna
						 * 
						 * */
						choose = false;
						break;
					}
				}
				/*
				 * jesli karta nie wystapila w pozostalych kolumnach, to karta zostaje wybrana
				 * */
				if (choose) // karta zostala wybrana
				{
					cards.add(c); // dodajemy do listy cards czyli naszych wybrancow 
					chosen = true; // zaznaczamy ze karta zostala wybrana
					break;
				}
			}
			/*
			 * jesli zadna karta z biezacej kolumny nie zostala wybrana, i mamy przypadek dwoch kolumn z dwoma kartami
			 * to oznacza ze kolumny sa identyczne i bierzemy karte z najmniesza  wartoscia z biezacej kolumny
			 * oraz karte z wartoscia wyzsza z nastepnej kolumny
			 * */
			if(!chosen && matrix.get(i).size() == 2 && matrix.get(i+1).size() == 2)
			{
				// przypadek gdy mamy dwie karty tej samej wartosci w dwoch kolarach
				cards.add(matrix.get(i).get(0));
				cards.add(matrix.get(i+1).get(1));
				break;
			}
		}
		
		/*
		 * ostatnie posortowanie wybranych kart w kolejnosci malejacej, aby porownywac dwa rozklady z jednakowa iloscia kart
		 * od najwyzszch kart
		 * 
		 * */
		Collections.sort(cards, Collections.reverseOrder()); // sortowanie do compareTo Handow, bo sprawdzamy karty od najwyzszej po kolei
		
		return cards;
	}

	public static Comparator<ArrayList<Card>> ColorListComparator 
   	= new Comparator<ArrayList<Card>>() 
   	{
			public int compare(ArrayList<Card> color1, ArrayList<Card> color2) 
			{
				
				if (color1.size() == 0 && color2.size() == 0)
					return 0; // jesli puste
				
				if (color1.size() == color2.size())
					return color1.get(color1.size()-1).compareTo(color2.get(color2.size()-1)); // c1 do c2 bo karty najwyzsze rosnaco
				
				return color2.size() - color1.size(); // kolumny malejaco
			}

   	};

	public String getCardsListAsString()
	{
		return getCards().toString();
	}
	
	public String toString()
	{
		return this.getCardList().toString();
	}
}
